package com.mutouren.common.nosql;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Element;

import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import com.mutouren.common.config.ConfigManager;
import com.mutouren.common.exception.ExceptionManager;
import com.mutouren.common.log.LogManager;
import com.mutouren.common.log.Logger;

public class MongoConfig {
	private static Logger errorLogger = LogManager.getLogger("SystemErrorLog");
	private List<ServerAddress> listAddress = new ArrayList<ServerAddress>();	
	private MongoClientOptions mongoOptions = new MongoClientOptions.Builder().build();
	private String database;
	private String clientName;

	public MongoConfig(String database) {
		try {
			load(database);
		} catch (Throwable t) {
			errorLogger.error(String.format("MongoConfig() init error! database: %s", database), t);
			throw ExceptionManager.doUnChecked(t);
		}
	}

	private void load(String database) throws UnknownHostException {
		List<Element> listMongo = ConfigManager.getElements("nosql/mongo/database");
		boolean isFind = false;
		for(Element e : listMongo) {
			if(e.attribute("name").getValue().equals(database)) {
				this.database = e.attribute("database").getValue();
				this.clientName = e.attribute("client_ref").getValue();
				loadClient(this.clientName);
				isFind = true;
				break;
			}
		}
		
		if(!isFind) {
			throw new RuntimeException(String.format(" mongoClient.database: %s load config fail", database));
		}	
	}
	
	private void loadClient(String clientName) throws UnknownHostException {
		List<Element> listClient = ConfigManager.getElements("nosql/mongo/client");
		for(Element e : listClient) {
			if(e.attribute("name").getValue().equals(clientName)) {
				String optionsName = e.attribute("mongooptions_ref").getValue();
				loadOptions(optionsName);
				
				@SuppressWarnings({ "unchecked"})
				List<Element> listElement = (List<Element>)e.selectNodes("socketaddress");
				for(Element e2 : listElement) {
					String ip = e2.attributeValue("ip");
					int port = Integer.parseInt(e2.attributeValue("port"));
					listAddress.add(new ServerAddress(ip, port));
				}
				break;
			}			
		}
		
		if(listAddress.size() == 0) {
			throw new RuntimeException(String.format(" mongoClient: %s load config fail", clientName));
		}		
	}

	private void loadOptions(String optionsName) {
		List<Element> listOptions = ConfigManager.getElements("nosql/mongo/mongooptions");
		Element elementOptions = null;
		if(listOptions == null) return;
		
		for(Element e : listOptions) {
			if(e.attribute("name").getValue().equals(optionsName)) {
				elementOptions = e;
				break;
			}
		}
		if(elementOptions == null) return;
		
		int minConnectionsPerHost = Integer.parseInt(((Element)elementOptions.selectSingleNode("minConnectionsPerHost")).attributeValue("value"));
		int connectionsPerHost = Integer.parseInt(((Element)elementOptions.selectSingleNode("connectionsPerHost")).attributeValue("value"));
		int maxConnectionIdleTime = Integer.parseInt(((Element)elementOptions.selectSingleNode("maxConnectionIdleTime")).attributeValue("value"));
		
		MongoClientOptions mongoOptions = new MongoClientOptions.Builder()
			.minConnectionsPerHost(minConnectionsPerHost)
			.connectionsPerHost(connectionsPerHost)
			.maxConnectionIdleTime(maxConnectionIdleTime)
			.build();
		
		this.mongoOptions = mongoOptions;
	}

	public MongoClientOptions getMongoOptions() {
		return mongoOptions;
	}

	public String getDatabase() {
		return database;
	}

	public String getClientName() {
		return clientName;
	}
	
	public List<ServerAddress> getListAddress() {
		return this.listAddress;
	}

}
